package api

import (
	"fmt"

	"github.com/gin-gonic/gin"
	"zhonghui/console/warehouse/dbx/db_zh_kernel"
	"zhonghui/console/warehouse/helperx"
	"zhonghui/console/warehouse/logx"
	"zhonghui/console/warehouse/modelx/model_zh_kernel"
	"zhonghui/console/warehouse/respx"

	"zhonghui/console/service"
	"zhonghui/console/structs"
)

func (server *Server) PostSignIn(c *gin.Context) {
	req := structs.PostSignInReq{}
	if err := c.ShouldBindJSON(&req); err != nil {
		respx.Bad(c, err)
		return
	}

	var userId uint
	var err error

	// 扫码登录、两步验证、手机密码登录
	if req.Code != "" {
		// 网页授权
		userId, err = service.SignInWithCode(c, req.Code)
		if err != nil {
			respx.Alert(c, "授权失败，请重试")
			return
		}
	} else if req.Otp != "" && req.OtpFlag != "" {
		// 解密用户id
		uid, err := helperx.HashIdDecode(req.OtpFlag)
		if err != nil {
			respx.Alert(c, "验证失败，请重试")
			return
		}

		// 查找用户
		user := model_zh_kernel.ConsoleManager{}
		if err := db_zh_kernel.ClientCtx(c).Where("id = ?", uid).Take(&user).Error; err != nil {
			respx.Alert(c, "安全码错误，请重试")
			return
		}
		userId = user.ID

		// 检查otp正确性
		if !service.IsValidOtp(req.Otp, user.OtpSecret, user.ID, req.ClientUid) {
			respx.Alert(c, "安全码错误，请重试")
			return
		}
	} else if req.Phone != "" && req.Password != "" {
		userId, err = service.SignInWithPhone(c, req.Phone, req.Password)
		if err != nil {
			respx.Alert(c, "登入信息错误")
			return
		}
	} else {
		respx.Alert(c, "授权信息不正确")
		return
	}

	if userId <= 0 {
		respx.Alert(c, "授权失败请重试")
		return
	}

	// 生成token
	token, err := service.IssueToken(userId, 86400*30)

	// 检查OTP 如需要则提示前端唤起otp输入页面
	if !(req.Otp != "" && req.OtpFlag != "") && service.NeedOtp(userId, req.ClientUid) {
		// 加密用户id
		hashUserId, err := helperx.HashIdEncode(int(userId))
		if err != nil {
			respx.Alert(c, "授权失败，请重试")
			return
		}

		// 查询头像和昵称并返回
		manager := model_zh_kernel.ConsoleManager{}
		if err := db_zh_kernel.ClientCtx(c).Where("id = ?", userId).Take(&manager).Error; err != nil {
			respx.Alert(c, "授权失败，请重试")
			return
		}

		name := fmt.Sprintf("%s - %s", manager.Nickname, manager.RealName)
		if manager.Nickname == "" {
			name = manager.RealName
		}

		resp := structs.SignInNeedOtpResp{
			OtpFlag: hashUserId,
			Name:    name,
		}

		respx.Success(c, resp, nil)
		return
	}

	resp := structs.PostSignInResp{
		Token:         token,
		TokenExpireIn: 86400,
		UserId:        userId,
	}

	respx.Success(c, resp, nil)
}

func (server *Server) PostBind(c *gin.Context) {
	req := structs.PostBindReq{}
	if err := c.ShouldBindJSON(&req); err != nil {
		respx.Bad(c, err)
		return
	}

	user := service.GetUserFromToken(c.GetHeader("Authorization"))
	if user == nil {
		respx.UnAuth(c)
		return
	}

	if err := service.BindWithCode(c, user.ID, req.Code); err != nil {
		logx.Zap().Errorw("绑定授权失败", "err", err)
		respx.Alert(c, "绑定授权失败，请重试")
		return
	}

	respx.Success(c, nil, nil)
}
